﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Xml.Linq;
using CeskyRozhlasRT.DataModel;

namespace CeskyRozhlasRT.Parsing
{
    public class StationDescriptionXmlParser : IStationDescriptionXmlParser
    {
        public StationInfo ParseStationDescription(String iXmlRepresentation)
        {
            IList<RadioStreamDescription> aStreams = new List<RadioStreamDescription>();
            try
            {
                var aDoc = XDocument.Parse(iXmlRepresentation);
                var aShortDescription = aDoc.Descendants("shortdescription").First().Value;
                var aName = aDoc.Descendants("shortname").First().Value;
                var aType = aDoc.Root.Attribute("type").Value;
                int aId = 0;
                Int32.TryParse(aDoc.Root.Attribute("id").Value, out aId);
                var aWebUid = aDoc.Root.Attribute("kod_webu").Value;
                var aImagePath = "ms-appx:///Assets/DarkGray.png";

                foreach (XElement aElement 
                    in from aElement 
                           in aDoc.Descendants("media") 
                       where aElement.Attribute("type") != null 
                       && aElement.Attribute("type").Value == "aplikace" 
                       select aElement)
                {
                    aImagePath = aElement.Attribute("url").Value;
                }

                foreach (var aCurrentElement in aDoc.Descendants("item"))
                {
                    aStreams.Add(parseStreamDescription(aCurrentElement));
                }

                return new StationInfo
                {
                    Uid = aId,
                    WebUid = aWebUid,
                    Title = aName,
                    ImagePath = aImagePath,
                    Schedule = new RadioSchedule
                    {
                        Uris = aDoc.Root.Element("program").Elements().Where(aElement => aElement.Name == "now" || aElement.Name == "next")
                        .Select(aElement => aElement.Attribute("url").Value)
                        .ToList(),
                        Shows = new ObservableCollection<RadioShow>()
                    },
                    Streams = aStreams,
                    Description = aShortDescription,
                    Type = aType
                };
            }
            // ReSharper disable once EmptyGeneralCatchClause
            catch
            {
                //TODO: add logging
            }
            return null;
        }

        private RadioStreamDescription parseStreamDescription(XElement iElement)
        {
            try
            {
                var aUri = iElement.Attribute(XName.Get("url")).Value;
                var aCodecType = iElement.Attribute(XName.Get("type")).Value;
                Int32 aBitrate = 0;
                if (iElement.Attribute("bitrate") != null)
                {
                    Int32.TryParse(iElement.Attribute("bitrate").Value, out aBitrate);
                }
                Int32 aFrequency = 0;
                if (iElement.Attribute("freq") != null)
                {
                    Int32.TryParse(iElement.Attribute("freq").Value, out aFrequency);
                }
                XAttribute aSoundAttribute = iElement.Attribute("sound");
                bool aStereo = aSoundAttribute != null && aSoundAttribute.Value != null && aSoundAttribute.Value == "stereo";
                XAttribute aVbrAttribute = iElement.Attribute("vbr");
                bool aVbr = aVbrAttribute != null && aVbrAttribute.Value != null && aVbrAttribute.Value == "true";

                return new RadioStreamDescription
                {
                    Uri = aUri, 
                    CodecType = aCodecType, 
                    Bitrate = aBitrate, 
                    Frequency = aFrequency,
                    Stereo = aStereo,
                    Vbr = aVbr
                };
            }
            // ReSharper disable once EmptyGeneralCatchClause
            catch
            {
                //Ignore
            }
            return null;
        }

    }
}
